#ifndef __CAM_WIDE_USB_H__
#define __CAM_WIDE_USB_H__

#include "base.pb.h"
#include "camera.pb.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/videodev2.h>

#include "opencv2/opencv.hpp"

enum CamWidePhotoState {
    CAM_WIDE_PHOTO_IDLE,
    CAM_WIDE_PHOTO_SINGEL,
    CAM_WIDE_PHOTO_BURST
};

//延时摄影状态
enum CamWideTimelapseState {
    CAM_WIDE_TIMELAPSE_IDLE,                 //空闲
    CAM_WIDE_TIMELAPSE_RECORDING             //延时摄影录制中
};

enum CamWideTimelapseFileState {
    CAM_WIDE_TIMELAPSE_FILE_GENERATEING,
    CAM_WIDE_TIMELAPSE_FILE_GENERATED
};

//control_id
#define V4L2_SET_BRIGHTNESS                             0x00980900 //设置亮度
#define V4L2_SET_CONTRAST                               0x00980901 //设置对比度
#define V4L2_SET_SATURATION                             0x00980902 //设置饱和度
#define V4L2_SET_HUE                                    0x00980903 //设置色调
#define V4L2_SET_WHITE_BALANCE_TEMPERATURE_MODE         0x0098090C //设置白平衡模式 0-手动 1-自动
#define V4L2_SET_GAMMA                                  0x00980910 //设置gamma
#define V4L2_SET_WHITE_BALANCE_TEMPERATURE              0x0098091A //设置白平衡值
#define V4L2_SET_SHARTNESS                              0x0098091B //设置清晰度
#define V4L2_SET_EXPOSURE_MODE                          0x009A0901 //设置曝光模式 1-手动 3-自动
#define V4L2_SET_EXPOSURE                               0x009A0902 //设置曝光值
#define V4L2_SET_FOCUS_MODE                             0x009A090C //设置对焦模式 0-手动 1-自动
#define V4L2_SET_FOCUS                                  0x009A090A //设置对焦值

void getCamWideJgpFrame(unsigned char* &frame, int &frame_size);

class CamWide {
public:
    CamWide();
    ~CamWide();

    int handleMessage(WsPacket& ws_packet);
    int isCameraOpen();
    int isCameraClose();
    int openCamera(bool binning);
    int openCamera(WsPacket& ws_packet);
    int closeCamera();
    int closeCamera(WsPacket& ws_packet);
    int setExpMode(int mode);
    int setExpMode(WsPacket& ws_packet);
    int getExpMode(int *value);
    int getExpMode(WsPacket& ws_packet);
    int setExp(double value);
    int setExp(WsPacket& ws_packet);
    int getExp(double *value);
    int getExp(WsPacket& ws_packet);
    int setGain(int value);
    int setGain(WsPacket& ws_packet);
    int getGain(int *value);
    int getGain(WsPacket& ws_packet);
    int setBrightness(int value);
    int setBrightness(WsPacket& ws_packet);
    int getBrightness(int *value);
    int getBrightness(WsPacket& ws_packet);
    int setContrast(int value);
    int setContrast(WsPacket& ws_packet);
    int getContrast(int *value);
    int getContrast(WsPacket& ws_packet);
    int setSaturation(int value);
    int setSaturation(WsPacket& ws_packet);
    int getSaturation(int *value);
    int getSaturation(WsPacket& ws_packet);
    int setHue(int value);
    int setHue(WsPacket& ws_packet);
    int getHue(int *value);
    int getHue(WsPacket& ws_packet);
    int setSharpness(int value);
    int setSharpness(WsPacket& ws_packet);
    int getSharpness(int *value);
    int getSharpness(WsPacket& ws_packet);
    int setWBMode(int mode);
    int setWBMode(WsPacket& ws_packet);
    int getWBMode(int *value);
    int getWBMode(WsPacket& ws_packet);
    int setWBCT(int value);
    int setWBCT(WsPacket& ws_packet);
    int getWBCT(int *value);
    int getWBCT(WsPacket& ws_packet);
    int getAllParams(WsPacket& ws_packet);
    int setAllParams(int exp_mode, int exp_index, int gain_index, int wb_mode,
                        int wb_index, int brightness, int contrast, int hue, int saturation, int sharpness);
    int setAllParams(WsPacket& ws_packet);
    
    
    int photograph();
    int photograph(WsPacket& ws_packet);
    int burstPhoto();
    int burstPhoto(WsPacket& ws_packet);
    int stopBurstPhoto();
    int stopBurstPhoto(WsPacket& ws_packet);
    int startTimeLapsePhotograph(WsPacket& ws_packet);
    int stopTimeLapsePhotograph(WsPacket& ws_packet);
    int stopTimeLapsePhotograph();

    void setPhotoState(CamWidePhotoState state);
    CamWidePhotoState getPhotoState();
    void setTimelapseState(CamWideTimelapseState state);
    CamWideTimelapseState getTimelapseState();
    void timeLapseGetNv12();

    inline void getJpgDecodeMat(cv::Mat& img) {
        uint8_t* frame = NULL;
        int frame_size;

        getCamWideJgpFrame(frame, frame_size);

        if (frame != NULL) {
            cv::Mat jpeg_mat(1, frame_size, CV_8UC1, frame);
            img = cv::imdecode(jpeg_mat, cv::IMREAD_UNCHANGED);
            free(frame);
        }
    }

    int getRecordLoadingCount();
    int getSessionBurstPhotoCount();
    int getBurstPhotoId();

    int getSessionTimelapseInterval();
    int getTimelapseElapsedTime();
    int getTimelapseOutTime();

private:
    int saveJpg(const std::string& jpg_path, uint8_t* frame, int frame_size);
};

#endif
